<template>
  <div class="dv-border-box-8" ref="borderBox8">
    <svg class="dv-border-svg-container" :width="width" :height="height">
      <defs>
        <path
            :id="path"
            :d="pathD"
            fill="transparent"
        />
        <radialGradient
            :id="gradient"
            cx="50%" cy="50%" r="50%"
        >
          <stop
              offset="0%" stop-color="#fff"
              stop-opacity="1"
          />
          <stop
              offset="100%" stop-color="#fff"
              stop-opacity="0"
          />
        </radialGradient>

        <mask :id="mask">
          <circle cx="0" cy="0" r="150" :fill="`url(#${gradient})`">
            <animateMotion
                :dur="`${dur}s`"
                :path="pathD"
                rotate="auto"
                repeatCount="indefinite"
            />
          </circle>
        </mask>
      </defs>

      <polygon :fill="backgroundColor" :points="`5, 5 ${width - 5}, 5 ${width - 5} ${height - 5} 5, ${height - 5}`"/>

      <use
          :stroke="mergedColor[0]"
          stroke-width="1"
          :xlink:href="`#${path}`"
      />

      <use
          :stroke="mergedColor[1]"
          stroke-width="3"
          :xlink:href="`#${path}`"
          :mask="`url(#${mask})`"
      >
        <animate
            attributeName="stroke-dasharray"
            :from="`0, ${length}`"
            :to="`${length}, 0`"
            :dur="`${dur}s`"
            repeatCount="indefinite"
        />
      </use>
    </svg>

    <div class="border-box-content">
      <slot></slot>
    </div>
  </div>
</template>

<script>
import { cloneDeep, debounce, mergeDeep, UUID2 } from "../../../../utils/utils";
import { computed, onMounted, ref, watch } from "vue";

export default {
  name: "DvBorderBox8",
  props: {
    color: {
      type: Array,
      default: () => ([])
    },
    dur: {
      type: Number,
      default: 3
    },
    backgroundColor: {
      type: String,
      default: "transparent"
    },
    reverse: {
      type: Boolean,
      default: false
    }
  },
  setup(props) {
    const id = UUID2(32);
    const borderBox8 = ref(null);
    const path = `border-box-8-path-${id}`;
    const gradient = `border-box-8-gradient-${id}`;
    const mask = `border-box-8-mask-${id}`;
    const defaultColor = ref(["#235fa7", "#4fd2dd"]);
    const mergedColor = ref([]);
    const width = ref(300);
    const height = ref(300);
    const mergeColor = () => {
      mergedColor.value = mergeDeep(cloneDeep(defaultColor.value), props.color || []);
    };
    watch(() => props.color, s => {
      mergeColor();
    });
    const length = computed(() => {
      return (width.value + height.value - 5) * 2;
    });
    const pathD = computed(() => {
      if (props.reverse) return `M 2.5, 2.5 L 2.5, ${height.value - 2.5} L ${width.value - 2.5}, ${height.value - 2.5} L ${width.value - 2.5}, 2.5 L 2.5, 2.5`;
      return `M2.5, 2.5 L${width.value - 2.5}, 2.5 L${width.value - 2.5}, ${height.value - 2.5} L2.5, ${height.value - 2.5} L2.5, 2.5`;
    });
    onMounted(() => {
      const ro = new ResizeObserver(entries => {
        handleResize(entries);
      });
      ro.observe(borderBox8.value);
      mergeColor();
    });
    const handleResize = debounce((entries) => {
      width.value = entries[0].contentRect.width;
      height.value = entries[0].contentRect.height;
    }, 100);
    return {
      length,
      pathD,
      path,
      mask,
      gradient,
      width,
      height,
      borderBox8,
      mergedColor,
      mergeColor,
      handleResize,
      defaultColor,
    };
  },
};
</script>

<style scoped>
.dv-border-box-8 {
  position: relative;
  width: 100%;
  height: 100%;
}

.dv-border-box-8 .dv-border-svg-container {
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0px;
  top: 0px;
}

.dv-border-box-8 .border-box-content {
  position: relative;
  width: 100%;
  height: 100%;
}
</style>
